//表格组件通用方法，排序，编辑列等
import { getToken } from '@/utils/auth'
import moment from 'moment'

const d = {}

/**
 * 表格属性对象 定义
 */
d.tableAttrs = [
  [
    { key: 'borderCell', text: '边框单元格', value: true },
    { key: 'borderBold', text: '边框加粗', value: false },
    //{ key: 'leftDisplay', text: '居左显示', value: true },
    { key: 'supportLineBreak', text: '支持换行', value: false },
    //{ key: 'dragAndSort', text: '拖拽排序', value: false }
  ]
]

/**
 * 计算多级表头的中所有的最后一级表头，用作表格内容的渲染
 * @param {Object} columnList
 */
d.calCols = function(columnList) {
  const colArr = []
  const digui = function(cols, isInherit, fixed, hidden) {
    for (const item of cols) {
      if (isInherit) {
        item.fixed = fixed
        item.hidden = hidden
      }
      if (item.children) {
        digui(item.children, true, item.fixed, item.hidden)
      } else {
        colArr.push(item)
      }
    }
  }
  digui(columnList)
  return colArr
}

/**
 * 计算表格标题区域合并列参数
 * @param {Object} columnList
 */
d.calSpan = function(columnList) {
  const hdArr = []
  const digui = function(level, cols) {
    if (!hdArr[level]) {
      hdArr[level] = []
    }
    for (const item of cols) {
      hdArr[level].push(item)
      if (item.children) {
        digui(level + 1, item.children)
      }
    }
  }
  digui(0, columnList)
  const subCount = function(obj, cur) {
    if (!cur) {
      cur = obj
    }
    if (obj.colspan === undefined) {
      obj.colspan = 0
    }
    if (cur.children) {
      for (const item of cur.children) {
        subCount(obj, item)
      }
    } else {
      ++obj.colspan
    }
  }
  for (const trIndex in hdArr) {
    const tr = hdArr[trIndex]
    for (const th of tr) {
      th.rowspan = !th.children ? hdArr.length - trIndex : 1
      subCount(th)
    }
  }
  return hdArr
}

/**
 * 为多级表头进行固定列位置分组
 * @param {Object} columnList
 * @param {Object} flag
 */
d.getGroupTitles = function(titleList, flag) {
  const arr = []
  for (const index in titleList) {
    const items = titleList[index]
    const arrTemp = []
    for (const temp of items) {
      if (temp.hidden) {
        continue
      }
      if (!flag || flag === 'center') {
        if (!temp.fixed || temp.fixed === 'center') {
          arrTemp.push(temp)
        }
      } else if (temp.fixed === flag) {
        arrTemp.push(temp)
      }
    }
    arr.push(arrTemp)
  }
  return arr
}

/**
 * 给行数据对象设置修改项标识
 * @param {Object} vm 组件实例
 * @param {Object} row 行对象
 * @param {Object} fieldInfo 列信息
 * @param {Object} value 非必填，如果该项有值就赋值该项再加标识
 */
d.setOutValue = function(vm, row, fieldInfo, value) {
  if (value !== undefined) {
    row[fieldInfo.field] = value
  }
  if (!row.hasOwnProperty('cEdited') || !row.cEdited) {
    Object.defineProperties(row, {
      cEdited: {
        value: {},
        writable: true,
        enumerable: false
      }
    })
  }
  row.cEdited[fieldInfo.field] = true
  // 将修改行添加进编辑行缓存
  vm.editedList.add(row)
}

/**
 * 判断是否允许编辑
 * @param {Object} edit 判断的编辑项，可以说boolean、function
 * @param {Object} row 行数据
 */
d.editEnable = function(edit, row) {
  if (edit) {
    if (typeof (edit) === 'function') {
      return edit(row)
    } else {
      return edit
    }
  }
  return false
}

/**
 * 开关组件切换
 * @param {Object} vm 组件实例
 * @param {Object} row 行数据
 * @param {Object} fieldInfo 字段信息
 */
d.switchTrigger = function(vm, e, row, fieldInfo) {
  const currentValue = row[fieldInfo.field]
  if (currentValue === fieldInfo.on) {
    row[fieldInfo.field] = fieldInfo.off
  } else if (currentValue === fieldInfo.off) {
    row[fieldInfo.field] = fieldInfo.on
  }
  d.setOutValue(vm, row, fieldInfo)
}

/**
 * 复选框组件切换
 * @param {Object} vm 组件实例
 * @param {Object} row 行数据
 * @param {Object} fieldInfo 字段信息
 */
d.checkBoxTrigger = function(vm, e, row, fieldInfo) {
  const currentValue = row[fieldInfo.field]
  if (currentValue === fieldInfo.on) {
    row[fieldInfo.field] = fieldInfo.off
  } else if (currentValue === fieldInfo.off) {
    row[fieldInfo.field] = fieldInfo.on
  }
  vm.$emit('change', row, fieldInfo.field)
  d.setOutValue(vm, row, fieldInfo)
}

/**
 * 根据Event事件获取目标target元素的尺寸以及位置
 * @param {Event} elEvent
 */
d.getElInfo = function(box, elEvent) {
  const boxRect = box.getBoundingClientRect()
  const tdRect = elEvent.path.find(el => el.tagName === 'TD').getBoundingClientRect()
  return {
    top: (tdRect.top - boxRect.top) + 'px',
    topNum: tdRect.top - boxRect.top,
    left: (tdRect.left - boxRect.left) + 'px',
    leftNum: tdRect.left - boxRect.left,
    height: (tdRect.height) + 'px',
    heightNum: (tdRect.height),
    width: (tdRect.width) + 'px',
    widthNum: (tdRect.width)
  }
}

/**
 * 组件位置自适应
 * @param {Object} editor 目标元素编辑状态信息
 * @param {Object} vm 组件实例
 */
d.autoOffset = function(editor, vm) {
  let isOffset = false
  // 获取非固定列左右可视范围
  const left = vm.tableFixedMargin.leftNum
  const right = vm.tableBoundingClientRect.width - vm.tableFixedMargin.rightNum - vm.scrollBarWidth
  let scrollLeft = vm.$refs.centerTableBody.scrollLeft
  let boxLeft = editor.leftNum
  if (editor.leftNum < left) {
    scrollLeft -= left - editor.leftNum
    boxLeft = left
    isOffset = true
  } else if (editor.leftNum + editor.widthNum > right) {
    scrollLeft += editor.leftNum + editor.widthNum - right
    boxLeft = right - editor.widthNum
    isOffset = true
  }
  vm.$refs.centerTableBody.scrollLeft = scrollLeft
  editor.left = boxLeft + 'px'
  editor.leftNum = boxLeft
  return isOffset
}

/**
 * 打开编辑框组件
 * @param {Object} vm 组件实例
 * @param {Object} row 行数据
 * @param {Object} fieldInfo 字段信息
 * @param {Object} tabTitle 字段集合
 */
d.openTextEditor = function(vm, e, row, fieldInfo, tabTitle) {
  const editor = d.getElInfo(vm.$el, e)
  if (fieldInfo.fixed !== 'left' && fieldInfo.fixed !== 'right') {
    d.autoOffset(editor, vm)
  }
  vm.$nextTick(() => {
    editor.type = 'text'
    editor.fieldName = fieldInfo.field
    editor.origValue = row[fieldInfo.field]
    editor.row = row
    editor.fieldInfo = fieldInfo
    editor.event = e
    editor.tabTitle = tabTitle
    vm.editor = editor
  })
}

/**
 * 打开数值框组件
 * @param {Object} vm 组件实例
 * @param {Object} row 行数据
 * @param {Object} fieldInfo 字段信息
 * @param {Object} tabTitle 字段集合
 */
d.openNumberEditor = function(vm, e, row, fieldInfo, tabTitle) {
  const editor = d.getElInfo(vm.$el, e)
  if (fieldInfo.fixed !== 'left' && fieldInfo.fixed !== 'right') {
    d.autoOffset(editor, vm)
  }
  vm.$nextTick(() => {
    editor.type = 'number'
    editor.fieldName = fieldInfo.field
    editor.origValue = row[fieldInfo.field]
    editor.row = row
    editor.fieldInfo = fieldInfo
    editor.event = e
    editor.tabTitle = tabTitle
    let decimal = fieldInfo.decimalColumn ? row[fieldInfo.decimalColumn] : fieldInfo.decimal
    decimal = decimal ? parseInt(decimal) : 0
    let range = fieldInfo.range
    if (typeof (fieldInfo.range) === 'function') {
      range = fieldInfo.range(row)
    }
    editor.oninput = function(e, callback) {
      delete row[editor.fieldName]
      // eslint-disable-next-line no-useless-escape
      let value = e.target.value.replace(/^\.|^e|[^\d^\.^e^\-^\+]+/g, '') || ''
      if (decimal !== undefined) {
        const dian = decimal > 0 ? 1 : 0
        const pattern = new RegExp(`[\-|0-9]\\d*\\.{0,${dian}}\\d{0,${decimal}}`, 'gi')
        value = (value.match(pattern) || [])[0]
      }
      // console.log(e);
      if (range !== undefined) {
        const min = range[0]
        const max = range[1]
        const temp = parseFloat(value)
        console.log('输入', min, max, temp)
        if ((min && temp < min) || (max && temp > max)) {
          console.log('超出范围')
          if (e.inputType === 'insertText') {
            value = e.target.value.substr(0, e.target.value.length - 1)
          } else if (e.inputType === 'insertFromPaste') {
            value = ''
          }
        }
      }
      if (value === undefined) {
        value = ''
      }
      e.target.value = value
      row[editor.fieldName] = value || null
      if (callback) {
        callback()
      }
    }
    vm.editor = editor
  })
}

/**
 * 打开下拉框组件
 * @param {Object} vm 组件实例
 * @param {Object} row 行数据
 * @param {Object} fieldInfo 字段信息
 * @param {Object} tabTitle 字段集合
 */
d.openSelector = function(vm, e, row, fieldInfo, tabTitle) {
  const editor = d.getElInfo(vm.$el, e)
  if (fieldInfo.fixed !== 'left' && fieldInfo.fixed !== 'right') {
    d.autoOffset(editor, vm)
  }
  vm.$nextTick(() => {
    editor.type = 'selector'
    editor.fieldName = fieldInfo.field
    editor.origValue = row[fieldInfo.field]
    editor.row = row
    editor.fieldInfo = fieldInfo
    editor.event = e
    editor.mode = fieldInfo.mode ? fieldInfo.mode : 'default'
    editor.value = row[fieldInfo.field]
    editor.setVal = function(v) {
      vm.editor.type = undefined
      vm.$set(row, fieldInfo.field, v)
    }
    if (fieldInfo.multi) {
      editor.mode = 'multiple'
      const arr = []
      if (row[fieldInfo.field]) {
        row[fieldInfo.field].split(',').forEach(el => {
          arr.push(fieldInfo.dataValType === 'number' ? parseInt(el) : el)
        })
      }
      editor.value = arr
      editor.setVal = function(v) {
        // vm.editor.type=undefined;
        vm.$set(row, fieldInfo.field, (v || []).join(','))
        editor.value = v
      }
    }
    editor.tabTitle = tabTitle
    editor.dataValue = fieldInfo.dataValue || 'value'
    editor.dataTitle = fieldInfo.dataTitle || 'name'
    let list = fieldInfo.dropdownList || []
    // 判断是否自定义行数据对应字段的下拉列表数据 - 不同显示
    if (fieldInfo.customDropdownList && typeof (fieldInfo.customDropdownList) === 'function') {
      list = fieldInfo.customDropdownList(row)
    }
    // 如果有load方法就为空数据，直至load中异步加载完再显示数据，否则直接使用list数据
    if (fieldInfo.load) {
      editor.list = []
      fieldInfo.load(row, list, datas => {
        editor.list = datas
      })
    } else {
      editor.list = list
    }
    if (fieldInfo.css) {
      editor.css = fieldInfo.css
    }
    vm.editor = editor
  })
}

/**
 * 打开树型下拉框
 * @param {Object} vm 组件实例
 * @param {Object} row 行数据
 * @param {Object} fieldInfo 字段信息
 * @param {Object} tabTitle 字段集合
 */
d.openTreeSelector = function(vm, e, row, fieldInfo, tabTitle) {
  const editor = d.getElInfo(vm.$el, e)
  if (fieldInfo.fixed !== 'left' && fieldInfo.fixed !== 'right') {
    d.autoOffset(editor, vm)
  }
  vm.$nextTick(() => {
    editor.type = 'tree'
    editor.fieldName = fieldInfo.field
    editor.origValue = row[fieldInfo.field]
    editor.row = row
    editor.fieldInfo = fieldInfo
    editor.event = e
    editor.tabTitle = tabTitle
    editor.expand = fieldInfo.expand !== false
    editor.treeData = fieldInfo.treeData || []
    if (typeof (fieldInfo.treeData) === 'function') {
      editor.treeData = fieldInfo.treeData(row)
    }
    // 判断是否自定义行数据对应字段的下拉列表数据 - 不同显示
    if (fieldInfo.customDropdownList && typeof (fieldInfo.customDropdownList) === 'function') {
      editor.treeData = fieldInfo.customDropdownList(row)
    }
    if (fieldInfo.css) {
      editor.css = fieldInfo.css
    }
    editor.treeAllData = fieldInfo.treeData
    vm.editor = editor
  })
}

/**
 * 打开日期框
 * @param {Object} vm 组件实例
 * @param {Object} row 行数据
 * @param {Object} fieldInfo 字段信息
 * @param {Object} tabTitle 字段集合
 */
d.openDatePicker = function(vm, e, row, fieldInfo, tabTitle) {
  const editor = d.getElInfo(vm.$el, e)
  if (fieldInfo.fixed !== 'left' && fieldInfo.fixed !== 'right') {
    d.autoOffset(editor, vm)
  }
  vm.$nextTick(() => {
    editor.type = 'date'
    editor.fieldName = fieldInfo.field
    editor.format = fieldInfo.format
    editor.origValue = row[fieldInfo.field]
    editor.row = row
    editor.fieldInfo = fieldInfo
    editor.mode = fieldInfo.mode ? fieldInfo.mode : 'date'
    editor.date = row[fieldInfo.field] ? moment(row[fieldInfo.field]) : null
    editor.event = e
    editor.tabTitle = tabTitle
    vm.editor = editor
  })
}

/**
 * 响应点击事件
 * @param {Object} vm 组件实例
 * @param {Object} row 行数据
 * @param {Object} fieldInfo 字段信息
 * @param {Object} tabTitle 字段集合
 */
d.clickEvent = function(vm, e, rowIndex, row, fieldInfo, tabTitle) {
  const editor = d.getElInfo(vm.$el, e)
  editor.origValue = row[fieldInfo.field]
  editor.row = row
  editor.fieldInfo = fieldInfo
  editor.event = e
  editor.tabTitle = tabTitle
  vm.editor = editor
  if (fieldInfo.click) {
    fieldInfo.click(vm, e, row)
  }
  vm.$emit('tdClick', row, fieldInfo.field, rowIndex)
}

/**
 * 打开表头菜单
 * @param {Object} vm 组件实例
 * @param {Object} fieldInfo 字段信息
 */
d.openTdMenu = function(vm, e, fieldInfo) {
  const editor = d.getElInfo(vm.$el, e)
  editor.top = editor.topNum - 1 + 'px'
  editor.left = editor.leftNum + 1 + 'px'
  editor.type = 'hdmenu'
  editor.fieldName = fieldInfo.field
  editor.fieldInfo = fieldInfo
  editor.event = e
  vm.editor = editor
}

/**
 * 获取下一个可自动获取焦点的元素
 * @param {Object} dom 起始元素
 * @param {Object} dataTitle 列信息集合
 */
d.getNextDom = function(dom, dataTitle) {
  const nextDom = dom.nextSibling
  if (!nextDom) {
    return null
  }
  if (nextDom.attributes.fi) {
    // 获得列数据的信息
    const fi = nextDom.attributes.fi.nodeValue
    const ty = dataTitle[fi].type
    let edit = dataTitle[fi].edit
    if (typeof (edit) === 'function') {
      edit = true
    }
    if (edit && ty && (ty === 'selector' || ty === 'text' || ty === 'number')) {
      return nextDom
    }
  }
  return d.getNextDom(nextDom, dataTitle)
}

/**
 * 正序排序
 * @param {Object} vm 组件实例对象
 * @param {Object} fieldInfo 列信息
 */
d.sortAsc = function(vm, fieldInfo) {
  // console.log("正序排序：",fn);
  let sortFunc
  switch (fieldInfo.type) {
    case 'switch':
      sortFunc = d.switchSort(1, fieldInfo)
      break
    case 'checkBox':
      sortFunc = d.checkBoxSort(1, fieldInfo)
      break
    case 'text':
      sortFunc = d.textSort(1, fieldInfo)
      break
    case 'number':
      sortFunc = d.numberSort(1, fieldInfo)
      break
    case 'selector':
      sortFunc = d.selectorSort(1, fieldInfo)
      break
    case 'tree':
      sortFunc = d.treeSort(1, fieldInfo)
      break
    case 'date':
      sortFunc = d.dateSort(1, fieldInfo)
      break
    case 'click':
      sortFunc = d.textSort(1, fieldInfo)
      break
  }
  // custom排序方式
  if (fieldInfo.type === 'custom' && fieldInfo.sortType) {
    switch (fieldInfo.sortType) {
      case 'switch':
        sortFunc = d.switchSort(1, fieldInfo)
        break
      case 'checkBox':
        sortFunc = d.checkBoxSort(1, fieldInfo)
        break
      case 'text':
        sortFunc = d.textSort(1, fieldInfo)
        break
      case 'number':
        sortFunc = d.numberSort(1, fieldInfo)
        break
      case 'selector':
        sortFunc = d.selectorSort(1, fieldInfo)
        break
      case 'tree':
        sortFunc = d.treeSort(1, fieldInfo)
        break
      case 'date':
        sortFunc = d.dateSort(1, fieldInfo)
        break
      case 'click':
        sortFunc = d.textSort(1, fieldInfo)
        break
    }
  }
  if (!sortFunc) {
    console.warn('未找到排序方法')
    return
  }
  if (vm.tableData || vm.tableData.length > 0) {
    if (vm.lastRowDontSort) {
      const lastRow = vm.tableData.pop()
      vm.tableData.sort(function(a, b) {
        return sortFunc(a, b)
      })
      vm.tableData.push(lastRow)
    } else {
      vm.tableData.sort(function(a, b) {
        return sortFunc(a, b)
      })
    }
  }
}

/**
 * 倒序排序
 * @param {Object} vm 组件实例对象
 * @param {Object} fieldInfo 列信息
 */
d.sortDesc = function(vm, fieldInfo) {
  // console.log("倒序排序：",fieldInfo.field);
  let sortFunc
  switch (fieldInfo.type) {
    case 'switch':
      sortFunc = d.switchSort(-1, fieldInfo)
      break
    case 'checkBox':
      sortFunc = d.checkBoxSort(-1, fieldInfo)
      break
    case 'text':
      sortFunc = d.textSort(-1, fieldInfo)
      break
    case 'number':
      sortFunc = d.numberSort(-1, fieldInfo)
      break
    case 'selector':
      sortFunc = d.selectorSort(-1, fieldInfo)
      break
    case 'tree':
      sortFunc = d.treeSort(-1, fieldInfo)
      break
    case 'date':
      sortFunc = d.dateSort(-1, fieldInfo)
      break
    case 'click':
      sortFunc = d.textSort(-1, fieldInfo)
      break
  }
  // custom排序方式
  if (fieldInfo.type === 'custom' && fieldInfo.sortType) {
    switch (fieldInfo.sortType) {
      case 'switch':
        sortFunc = d.switchSort(-1, fieldInfo)
        break
      case 'checkBox':
        sortFunc = d.checkBoxSort(-1, fieldInfo)
        break
      case 'text':
        sortFunc = d.textSort(-1, fieldInfo)
        break
      case 'number':
        sortFunc = d.numberSort(-1, fieldInfo)
        break
      case 'selector':
        sortFunc = d.selectorSort(-1, fieldInfo)
        break
      case 'tree':
        sortFunc = d.treeSort(-1, fieldInfo)
        break
      case 'date':
        sortFunc = d.dateSort(-1, fieldInfo)
        break
      case 'click':
        sortFunc = d.textSort(-1, fieldInfo)
        break
    }
  }
  if (!sortFunc) {
    console.log('未找到排序方法')
    return
  }
  if (vm.tableData || vm.tableData.length > 0) {
    if (vm.lastRowDontSort) {
      const lastRow = vm.tableData.pop()
      vm.tableData.sort(function(a, b) {
        return sortFunc(a, b)
      })
      vm.tableData.push(lastRow)
    } else {
      vm.tableData.sort(function(a, b) {
        return sortFunc(a, b)
      })
    }
  }
}

/**
 * 开关排序
 * @param type
 * @param fieldInfo
 * @returns {function(*, *): *}
 */
d.switchSort = function(type, fieldInfo) {
  const field = fieldInfo.field
  const t = fieldInfo.on
  return function(a, b) {
    const t1 = a[field] === t ? 1 : 0
    const t2 = b[field] === t ? 1 : 0
    return type * (t1 - t2)
  }
}

/**
 * 复选框排序
 * @param type
 * @param fieldInfo
 * @returns {function(*, *): *}
 */
d.checkBoxSort = function(type, fieldInfo) {
  const field = fieldInfo.field
  const t = fieldInfo.on
  return function(a, b) {
    const t1 = a[field] === t ? 1 : 0
    const t2 = b[field] === t ? 1 : 0
    return type * (t1 - t2)
  }
}

/**
 * 文本排序
 * @param type
 * @param fieldInfo
 * @returns {function(*, *): *}
 */
d.textSort = function(type, fieldInfo) {
  const field = fieldInfo.field
  const formater = fieldInfo.formater ? fieldInfo.formater : function(data) {
    return String(data)
  }
  return function(a, b) {
    const t1 = a[field] ? formater(a[field]) : ''
    const t2 = b[field] ? formater(b[field]) : ''
    return type * (t1.localeCompare(t2, 'zh'))
  }
}

/**
 * 数字排序
 * @param type
 * @param fieldInfo
 * @returns {function(*, *): *}
 */
d.numberSort = function(type, fieldInfo) {
  const field = fieldInfo.field
  return function(a, b) {
    const t1 = a[field] ? parseFloat(a[field]) : 0
    const t2 = b[field] ? parseFloat(b[field]) : 0
    return type * (t1 - t2)
  }
}

/**
 * 下拉框排序
 * @param type
 * @param fieldInfo
 * @returns {function(*, *): *}
 */
d.selectorSort = function(type, fieldInfo) {
  const field = fieldInfo.field
  const formater = fieldInfo.formater ? fieldInfo.formater : function(data) {
    return String(data)
  }
  return function(a, b) {
    const t1 = a[field] ? formater(a[field]) : ''
    const t2 = b[field] ? formater(b[field]) : ''
    return type * (t1.localeCompare(t2, 'zh'))
  }
}

/**
 * 树形组件排序
 * @param type
 * @param fieldInfo
 * @returns {function(*, *): *}
 */
d.treeSort = function(type, fieldInfo) {
  const field = fieldInfo.field
  const formater = fieldInfo.formater ? fieldInfo.formater : function(data) {
    return String(data)
  }
  return function(a, b) {
    const t1 = a[field] ? formater(a[field]) : ''
    const t2 = b[field] ? formater(b[field]) : ''
    return type * (t1.localeCompare(t2, 'zh'))
  }
}

/**
 * 日期排序
 * @param type
 * @param fieldInfo
 * @returns {function(*, *): *}
 */
d.dateSort = function(type, fieldInfo) {
  const field = fieldInfo.field
  const formater = fieldInfo.formater ? fieldInfo.formater : function(data) {
    return String(data)
  }
  return function(a, b) {
    const t1 = a[field] ? formater(a[field]) : ''
    const t2 = b[field] ? formater(b[field]) : ''
    return type * (t1.localeCompare(t2, 'zh'))
  }
}

/**
 * 将数组根据唯一标识转换为Map字典
 * @param arr 下拉数据
 * @param flag 当前值
 * @returns {Map<any, any>}
 */
d.arrToMap = function(arr, flag) {
  const map = new Map()
  for (const item of arr) {
    map.set(item[flag], item)
  }
  return map
}

/**
 * 将树型数组根据唯一标识转换为Map字典
 * @param treeArr 数据
 * @param children 子节点字段
 * @param dataTitle 标题字段
 * @param dataValue 值字段
 * @returns {Map<any, any>}
 */
d.treeArrToMap = function(treeArr, children, dataTitle, dataValue) {
  const dic = new Map()
  const addTreeDic = function(node) {
    dic.set(node[dataValue], node[dataTitle])
    const subNode = node[children]
    if (subNode && subNode.length > 0) {
      for (const item of subNode) {
        addTreeDic(item)
      }
    }
  }
  for (const nodeItem of treeArr) {
    addTreeDic(nodeItem)
  }
  return dic
}

/**
 * 列宽自适应计算
 * @param {Object} containerWidth 容器的宽度
 * @param {Object} fixedSet 定义了固定列的列集合
 * @param {Object} nofixedSet 没有定义固定列的列集合
 */
d.calColumnWidth = function(containerWidth, fixedSet, nofixedSet) {
  // 可视区域宽度（可视宽度=容器宽度-固定列宽度）
  let visibleWidth = containerWidth
  for (const item of fixedSet) {
    visibleWidth -= item.width
  }
  // 由于存在边框1px，这里把最第一个固定列加长1px
  for (const item of fixedSet) {
    if (item.fixed === 'right') {
      item.offsetWidth = 1
      break
    }
  }
  // 已经定义的列宽度
  let allWidth = 0
  for (const item of nofixedSet) {
    allWidth += item.width
  }
  // 差值，未占满可视区域的宽度值，如果为负表示超过容器宽度（多减2个像素是因为边框导致多出2px）
  const chazhi = visibleWidth - allWidth - 2
  // 未占满容器，把差值等比例分给属性
  if (chazhi > 0) {
    // 给定义宽度的列等比例分差值
    for (const item of nofixedSet) {
      const result = Math.round(item.width / allWidth * chazhi)
      // console.log(item.width,result);
      item.width += result
    }
  }
}

/**
 * 判断是否是对象
 * @param obj
 * @returns {boolean}
 */
d.isObj = function(obj) {
  return (typeof obj === 'object') && obj !== null
}

/**
 * 深拷贝对象
 * @param obj
 * @param hash
 * @returns {*}
 */
d.copyObj = function(obj, hash = new WeakMap()) {
  let cloneObj
  const Constructor = obj.constructor
  switch (Constructor) {
    case RegExp:
      cloneObj = new Constructor(obj)
      break
    case Date:
      cloneObj = new Constructor(obj.getTime())
      break
    default:
      if (hash.has(obj)) return hash.get(obj)
      cloneObj = new Constructor()
      hash.set(obj, cloneObj)
  }
  for (const key in obj) {
    cloneObj[key] = d.isObj(obj[key]) ? d.copyObj(obj[key], hash) : obj[key]
  }
  if (typeof cloneObj !== 'function') {
    cloneObj._c_meta_ = obj
  }
  return cloneObj
}

/**
 * 原生ajax导出excel=》未携带token
 * @param filename excel文件名称
 * @param url 请求路径
 * @param params 需要导出的数据
 */
d.downloadExcel = function(filename, url, params) {
  // 生成原生XMLHttpRequest对象
  const createXHR = () => {
    if (window.ActiveXObject) {
      // eslint-disable-next-line no-undef
      return new ActiveXObject('Microsoft.XMLHTTP')
    } else if (window.XMLHttpRequest) {
      return new XMLHttpRequest()
    }
  }
  let xhh = createXHR()
  xhh.open('post', process.env.VUE_APP_BASE_API + url)
  xhh.setRequestHeader('Api-Admin-Token', getToken())
  xhh.setRequestHeader('Content-Type', 'application/json')
  xhh.responseType = 'blob'
  // 生成excel
  xhh.onreadystatechange = function() {
    if (xhh.readyState === 4 && xhh.status === 200) {
      const blob = new Blob([xhh.response], {
        type: 'application/vnd.ms-excel'
      })
      const url = window.URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.style.display = 'none'
      link.href = url
      link.setAttribute('download', filename + '.xls')
      document.body.appendChild(link)
      link.click()
      // 下载完成移除元素
      document.body.removeChild(link)
      // 释放掉blob对象
      window.URL.revokeObjectURL(url)
    }
  }
  xhh.send(params)
}

/**
 * 获取最后标题行
 * @param preTitles
 * @param titleList
 */
d.getLastTitleRow = function(preTitles, titleList) {
  const diedai = (item) => {
    if (item.children) {
      item.children.forEach(el => {
        el.parent = {
          key: item.field,
          value: item.title,
          rowspan: item.rowspan,
          colspan: item.colspan,
          copy_num: item.rowspan - 1,
          parent: item.parent
        }
        diedai(el)
      })
    } else if (!item.children && item.hasOwnProperty('field')) {
      titleList.push({
        key: item.field,
        value: item.title,
        rowspan: item.rowspan,
        colspan: item.colspan,
        copy_num: item.rowspan - 1,
        parent: item.parent
      })
    }
  }
  preTitles.forEach(el => {
    diedai(el)
  })
}

/**
 * 创建最终的标题数据
 * @param titleList
 */
d.buildTitleList = function(titleList) {
  for (let i = 0; i < titleList.length; i++) {
    for (let j = 0; j < titleList[i].row.length; j++) {
      const targetCell = titleList[i].row[j]
      if (!targetCell.target) {
        targetCell.mergeRow = parseInt(targetCell.rowspan) - 1
        targetCell.mergeCol = parseInt(targetCell.colspan) - 1
        for (let row = 0; row < targetCell.rowspan; row++) {
          titleList[i + row].row[j].target = true
        }
        for (let col = 0; col < targetCell.colspan; col++) {
          titleList[i].row[j + col].target = true
        }
      }
    }
  }
}

export { d }
